using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Cysharp.Threading.Tasks;
using HybridCLR;
using UnityEngine;
using Core.Runtime;

namespace GameLauncher.Runtime
{
    public class LoadAssemblyState : AssemblyLoaderState
    {
        #region Core Workflow

        public override async UniTask<StateResult> Execute()
        {
            await UniTask.Yield();
            ReportProgress("正在加载资源...");

            try
            {
                ResetState();
                
                var metadataTask = LoadAOTMetadataAssemblies();
                var hotfixTask = LoadHotUpdateAssemblies();

                await UniTask.WhenAll(metadataTask, hotfixTask);
                await UniTask.WaitUntil(() => mAssemblyLoadComplete && mMetadataLoadComplete);

                return LaunchGame() ? StateResult.Success() : StateResult.Failure("游戏启动失败");
            }
            catch (Exception e)
            {
                Debug.LogError($"资源加载异常: {e}");
                return StateResult.Failure($"资源加载失败: {e.Message}");
            }
        }

        #endregion

        #region Assembly Loading

        private async UniTask LoadHotUpdateAssemblies()
        {
            mAssemblyLoading = true;
            
            foreach (var dllName in GameSettings.HotUpdateAssemblies)
            {
                var assetPath = GetAssemblyAssetPath(dllName);
                Debug.Log($"加载热更程序集: {assetPath}");
                
                mPendingAssemblyCount++;
                var handler = await AssetManager.LoadAssetAsync<TextAsset>(assetPath);
                HandleHotUpdateAssemblyLoaded(handler);
            }

            mAssemblyLoading = false;
            ValidateLoadCompletion(ref mAssemblyLoadComplete, mPendingAssemblyCount, mAssemblyLoading);
        }

        private void HandleHotUpdateAssemblyLoaded(AssetHandler<TextAsset> handler)
        {
            try
            {
                mPendingAssemblyCount--;

                if (!ValidateAssetHandler(handler, ref mFailedAssemblyCount))
                    return;

                var assembly = LoadAssembly(handler.Asset.bytes, handler.Asset.name);
                RegisterAssembly(assembly, handler.Asset.name);
            }
            finally
            {
                ReleaseAssetHandler(handler);
                ValidateLoadCompletion(ref mAssemblyLoadComplete, mPendingAssemblyCount, mAssemblyLoading);
            }
        }

        #endregion

        #region AOT Metadata Handling

        private async UniTask LoadAOTMetadataAssemblies()
        {
            mMetadataLoading = true;
            
            foreach (var dllName in GameSettings.AOTMetaAssemblies)
            {
                var assetPath = GetAssemblyAssetPath(dllName);
                Debug.Log($"加载AOT元数据: {assetPath}");
                
                mPendingMetadataCount++;
                var handler = await AssetManager.LoadAssetAsync<TextAsset>(assetPath);
                HandleMetadataLoaded(handler);
            }

            mMetadataLoading = false;
            ValidateLoadCompletion(ref mMetadataLoadComplete, mPendingMetadataCount, mMetadataLoading);
        }

        private unsafe void HandleMetadataLoaded(AssetHandler<TextAsset> handler)
        {
            try
            {
                mPendingMetadataCount--;

                if (!ValidateAssetHandler(handler, ref mFailedMetadataCount))
                    return;

                fixed (byte* ptr = handler.Asset.bytes)
                {
                    var err = HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(
                        handler.Asset.bytes, 
                        HomologousImageMode.SuperSet
                    );
                    Debug.Log($"AOT元数据加载: {handler.Asset.name} => {(LoadImageErrorCode)err}");
                }
            }
            finally
            {
                ReleaseAssetHandler(handler);
                ValidateLoadCompletion(ref mMetadataLoadComplete, mPendingMetadataCount, mMetadataLoading);
            }
        }

        #endregion

        #region Helper Methods

        private void ResetState()
        {
            mAssemblyLoadComplete = false;
            mMetadataLoadComplete = false;
            mPendingAssemblyCount = 0;
            mPendingMetadataCount = 0;
            mFailedAssemblyCount = 0;
            mFailedMetadataCount = 0;
            HotfixAssemblies.Clear();
        }

        private bool ValidateAssetHandler(AssetHandler<TextAsset> handler, ref int errorCounter)
        {
            if (handler.IsValid && handler.Asset != null) 
                return true;

            errorCounter++;
            Debug.LogWarning($"资源加载失败: {handler.Name}");
            return false;
        }

        private void ValidateLoadCompletion(ref bool flag, int pending, bool loading)
        {
            flag = !loading && pending == 0;
        }

        private string GetAssemblyAssetPath(string dllName)
        {
            return NormalizePath(Path.Combine("Assets", GameSettings.AssemblyAssetPath, $"{dllName}{GameSettings.AssemblyAssetExtension}"));
        }

        private static string NormalizePath(string path) => path?.Replace('\\', '/');

        private Assembly LoadAssembly(byte[] bytes, string name)
        {
            try
            {
                var assembly = Assembly.Load(bytes);
                Debug.Log($"程序集加载成功: {assembly.GetName().Name}");
                return assembly;
            }
            catch (BadImageFormatException ex)
            {
                Debug.LogError($"无效程序集格式: {name}\n{ex}");
                throw;
            }
        }

        private void RegisterAssembly(Assembly assembly, string assetName)
        {
            HotfixAssemblies.Add(assembly);
            
            if (assetName.Equals(GameSettings.LogicMainDll, StringComparison.Ordinal))
            {
                MainLogicAssembly = assembly;
            }
        }

        private void ReleaseAssetHandler(AssetHandler<TextAsset> handler)
        {
            if (handler.IsValid)
                AssetManager.UnloadAsset(handler);
        }

        #endregion

        #region Game Launch

        private bool LaunchGame()
        {
            ReportProgress("资源加载完成，启动游戏...");
            
            if (!ValidateMainAssembly())
                return false;

            HotFixUI.Release();
            return Launcher.TryLaunchGame(MainLogicAssembly, HotfixAssemblies);
        }

        #endregion
        
        #region State Variables

        private bool mAssemblyLoadComplete;
        private bool mMetadataLoadComplete;
        private bool mAssemblyLoading;
        private bool mMetadataLoading;

        private int mPendingAssemblyCount;
        private int mPendingMetadataCount;
        private int mFailedAssemblyCount;
        private int mFailedMetadataCount;

        #endregion
    }
}
